package cn.xinfei.xdecision.engine.runner.executor;

import cn.xinfei.xdecision.engine.runner.context.XDecisionContext;
import cn.xinfei.xdecision.engine.runner.executor.model.StateTransmitModel;
import cn.xinfei.xdecision.engine.runner.executor.strategy.IEngineRunner;
import com.dianping.cat.Cat;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.Tags;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

import static cn.xinfei.xdecision.constant.EngineResultEnum.EXCEPTION_END;
import static cn.xinfei.xdecision.constant.EngineResultEnum.SUCCESS_END;

/**
 * 抽象的测试handler
 * 可支持nodeHandler 和 componentHandler
 *
 * @param <T>
 */
@Slf4j
public class ExamHandler<T> extends AbsNodeHandler<T> {

    private String code;
    private AbsNodeHandler handler;

    public ExamHandler(AbsNodeHandler nodeHandler) {
        this.handler = nodeHandler;
        this.code = nodeHandler.getCode();
        this.nodeType = nodeHandler.getNodeType();
        nodeHandler.init();
    }


    public StateTransmitModel handler() {
        if (handler instanceof NodeHandler) {
            return nodeHandler();
        }
        return handler.handler();
    }

    public StateTransmitModel nodeHandler() {
        StateTransmitModel stateTransmitModel = XDecisionContext.getContext().getStateContext();
        Map<String, Object> nodeInput = null;
        IEngineRunner iEngineRunner = handler.getEngineNodeRunner();
        try {
            //1.加载变量= handler.getIEngineRunner();
            iEngineRunner.getNodeFieldValue(handler);
            //2.获取节点输入
            nodeInput = iEngineRunner.getNodeInput(handler);
            //4.执行节点逻辑
            stateTransmitModel = iEngineRunner.runNode(handler);
        } catch (Exception e) {
            //7.一个节点执行异常，是否继续走后面的节点???
            log.error("节点执行异常,决策流终止，error={}", e.getMessage(), e);
            Cat.logError(e);
            Metrics.counter("xdecision_error_total", Tags.of("node", handler.getNodeType())).increment();
            return stateTransmitModel.setEngineResultEnum(EXCEPTION_END);
        }

        iEngineRunner.setNodeOutput(handler);

        //9.判断节点是否终止
        boolean terminalCondition = iEngineRunner.terminalCondition(handler, new HashMap<>(),nodeInput);

        //节点输出，要包含全部的输入输出和过程，凡是作为结果配置的，都进行输出
        //8.获取节点输出
        Map<String, Object> nodeOutput = iEngineRunner.getNodeOutput(handler);
        //10.打印节点日志
        iEngineRunner.after(handler, stateTransmitModel, nodeOutput, nodeInput);
        return stateTransmitModel.setEngineResultEnum(SUCCESS_END);
    }

    @Override
    public String getCode() {
        return code;
    }

    @Override
    public AbsNodeHandler getHandler() {
        return handler;
    }

    @Override
    public void push() {

    }

    @Override
    public void pop( StateTransmitModel transmitModel) {

    }

    @Override
    public void tracer() {

    }
}